home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / programm.ing / falcon / nt_dsp2.lzh / NT_DSP2.MSA / BENCH / F-96 < prev    next >
Encoding:
Text File  |  1988-07-22  |  24.1 KB  |  418 lines

  1.      opt  nomd,mex 
  2.      page 132,60,1,1 
  3. ;*******************************************
  4. ;Motorola Austin DSP Operation  June 30,1988
  5. ;*******************************************
  6. ;DSP96002
  7. ;Peripheral to Memory FFT - 1024 point
  8. ;File name: F-96.
  9. ;**************************************************************************
  10. ;    Maximum sample rate:  954 us at 27.0 MHz
  11. ;    Memory Size: Prog:  317 words ; Data:  6146 words
  12. ;    Number of clock cycles: 25760  (12880 instruction cycles)
  13. ;    Clock Frequency:    27.0MHz
  14. ;    Instruction cycle time:  74.1ns
  15. ;**************************************************************************
  16.  
  17. fftreal2  macro     points,data,odata,coef,ptr1,ptr2,ad 
  18. fftreal2  ident     1,2 
  19. ; Radix 2 Decimation in Time In-Place Fast Fourier Transform Routine 
  20. ;    Real input data - normally ordered 
  21. ;        Real data in Y memory 
  22. ;    Complex output data - normally ordered 
  23. ;        Real data in X memory 
  24. ;        Imaginary data in Y memory 
  25. ;    Coefficient lookup table 
  26. ;        -Cosine value in X memory 
  27. ;        -Sine value in Y memory 
  28. ; Macro Call - fftreal2   points,data,outdata,coef,ptr1,ptr2,ad
  29. ;    points     number of points (2-32768, power of 2) 
  30. ;    data       start of data buffer 
  31. ;    outdata    output data buffer 
  32. ;    coef    start of sine/cosine table 
  33. ;    ptr1  address of pointer to input data block 1
  34. ;    ptr2  address of pointer to input data block 2
  35. ;    ad    address of memory-mapped a/d
  36. ;
  37. ;    dma set-up
  38. ;
  39.      move #data,x:ptr1             ;set up buffer pointers
  40.      move #data+points,x:ptr2      ;
  41.      move #ad,x:$ffffffde          ;a/d memory location into dma source reg.
  42.      move #0,x:$ffffffdd           ;no offset for source reg.
  43.      move #2*points-1,x:$ffffffdb  ;modulo 2*points for input data collection
  44.      move #1,x:$ffffffd9           ;offset = 1 for data storage
  45.      move #data,x:$ffffffda        ;input data base address
  46.      move #points,x:$ffffffdc      ;dma counter = 1024
  47.      move #$80008036,x:$ffffffd8   ;start dma in block mode
  48. ;
  49. ;    test if dma ready, if so switch buffer pointers
  50. ;
  51. strt jclr #28,x:$ffffffd8,strt     ;wait until dma is done
  52.      move #points,x:$ffffffdc      ;if so, reinitialize dma counter
  53.      move #$80008036,x:$ffffffd8   ;restart dma,
  54.      move ptr1,d1.l                ;and swap buffer pointers
  55.      move ptr2,d1.m                ;
  56.      move d1.l,ptr2                ;
  57.      move d1.m,ptr1                ;
  58. ;
  59.  
  60. ;    do fft
  61.      move ptr2,r0                  ;point to data 
  62.      move #points/4,n0             ;offset between input points 
  63.      move #points-1,m0             ;mod on input pointer 
  64.      move r0,r4                    ;ar' pointer 
  65.      move (r0)+n0                  ;point to br' 
  66.      move r0,r5                    ;br' pointer 
  67.      move (r0)+n0                  ;point to c' 
  68.      move r0,r6                    ;cr', ci' pointer 
  69.      move r4,r0                    ;point r0 back to ar 
  70. ; Do first and second Radix 2 FFT passes 
  71. ;    y:ar' = x:ar + x:cr + x:br + x:dr 
  72. ;    y:br' = x:ar + x:cr - x:br - x:dr 
  73. ;    x:cr' = y:ar - x:cr 
  74. ;    y:cr' = x:dr - x:br 
  75.      move                          y:(r0)+n0,d0.s      ;get ar 
  76.      move                          y:(r0)+n0,d1.s      ;get br 
  77.      move                          y:(r0)+n0,d2.s      ;get cr 
  78.      faddsub d0,d2                 y:(r0)+n0,d3.s      ;cr'=ar-cr,ar+cr,get dr 
  79.      do n0,_first2                                     ;do first 2 passes 
  80.      fsubr d1,d3    d0.s,x:(r6)    d3.s,d4.s           ;dr-br, save cr', copy dr 
  81.      fadd d1,d4     x:(r0)+,d7.s   d3.s,y:(r6)+        ;dr+br, update r0, save ci' 
  82.      faddsub d2,d4                 y:(r0)+n0,d0.s      ;(ar+cr)(-+)(dr+br) 
  83.      move           d2.s,x:(r5)+   y:(r0)+n0,d1.s      ;save br', get br 
  84.      move                          d4.s,y:(r4)+        ;save ar' 
  85.      move                          y:(r0)+n0,d2.s      ;get cr 
  86.      faddsub   d0,d2               y:(r0)+n0,d3.s      ;ar-cr,ar+cr,get dr 
  87. _first2 
  88. ; Do next passes 
  89.      move #points/8,n5                            ;spacing, for 1024 spacing=128 
  90.      move ptr2,r2                                 ;pointer to data      
  91.  
  92.      do   #@cvi(@log(points)/@log(2)-2.5),_next   ;7 passes for 1024 pts 
  93.      move r2,r5                                   ;reset pointer to data  
  94.      move n5,n0                                   ;same offset 
  95.      move r5,r0                                   ;ar pointer 
  96.      move (r5)+n5                                 ;+1/4 
  97.      move r5,r4                                   ;br pointer 
  98.      move (r5)+n5                                 ;+1/2 
  99.      move r5,r1                                   ;ci pointer 
  100.      move (r5)+n5                                 ;+3/4 
  101.  
  102.      move           x:(r5)+,d0.s   y:(r0)+n0,d4.s ;get dr, get ar 
  103.      do n0,_inner 
  104.      fneg d0                       y:(r0)-n0,d1.s ;ci'=-dr, get br 
  105.      faddsubr  d4,d1               d0.s,y:(r1)+   ;br'=ar-br,ar'=ar+br, save ci' 
  106.      move           d4.s,x:(r4)+   d1.s,y:(r0)+   ;save br', save ar' 
  107.      move           x:(r5)+,d0.s   y:(r0)+n0,d4.s ;get dr, get ar 
  108. _inner 
  109.      move n5,a                                    ;get bflys/pass 
  110.      lsr  a                                       ;/2 
  111.      move a1,n5                                   ;put back 
  112. _next 
  113.  
  114. ;    special pass: real input (4-point), output in normal order. The 4-th 
  115. ;    output point is stored as the complex conjugate of the 3 rd.
  116. ;
  117.      move #data,r0                                ;input pointer 
  118.      move #odata,r4                               ;output pointer 
  119.      move #points/2,n4   
  120.      move #0,m4                                   ;bit reverse output 
  121.  
  122.      move                          y:(r0)+,d0.s   ;get ar 
  123.      move                          y:(r0)+,d4.s   ;get br 
  124.      faddsubr d0,d4 x:(r0)+,d1.s                  ;get cr 
  125.      move                          d4.s,y:(r4)+n4 ;save ar'
  126.      move           x:(r0)+,d2.s                  ;get dr
  127.      fneg d2        d2.s,d5.s      d0.s,x:(r4)+n4 ;copy dr, save br' 
  128.      move           d1.s,x:(r4)                   ;save cr' 
  129.      move                          d2.s,y:(r4)+n4 ;save ci' 
  130.      move           d1.s,x:(r4)                   ;save cr' 
  131.      move                          d5.s,y:(r4)+n4 ;save ci'* 
  132.  
  133.  
  134. ;
  135. ;Do first (2-point) complex fft (this has one "last pass" only) with normally ordered
  136. ;output data and conjugate reverse storage of the next two points
  137. ;
  138.      move      #4,n2               ;offset for input data pointer
  139.      move      r4,n7               ;initialize output data pointer
  140.      move      (r2)+n2             ;adjust input data pointer
  141.      move      #0,m6               ;bit-reversed addressing for r6
  142.      move      #coefsize/2,n6
  143.      
  144. ; last pass
  145. ;
  146.       move      r2,r0                   ;Point to input data block
  147.       move      n7,r4                   ;r4 points to A output
  148.       move      #2*odata+points,r3      ;initialization of conjugate reverse pointer
  149.       move      #-1,m3                  ;r3 (conjugate reverse pointer) decrements linearly in initialization
  150.       move      r4,n3                   ;offset for conjugate pointer initialization
  151.       lea       (r0)+,r1                ;r1 points to B input
  152.       move      (r3)-n3                 ;r3 now has end of next output data block
  153.       move      #0,m3                   ;r3 will decrement bit-reversed in output storage
  154.       move      #points/2,n3            ;correct offset for reverse counter
  155.       move      #2,n0                   ;offset is 2 for A input pointer
  156.       lea       (r3)+n3,r6              ;r6 now contains the next output pointer a starting address
  157.       move      r6,n7                   ;n7 contains next output data block starting address
  158.       move      #coef+coefsize/4,r6     ;r6 points to twiddle factors  
  159.       move      n0,n1                   ;offset is 2 for B input pointer
  160.       move      #points/4,n4            ;offset is #points/4 for A output pointer
  161.       move      n4,n5                   ;offset is #points/4 for B output pointer
  162.       move      #0,m4                   ;bit reversed addressing for A output pointer
  163.       lea      (r4)+n4,r5               ;r5 points to B output by adding points/4 once----|
  164.       move      m4,m5                   ;bit reversed addressing for B output pointer     |
  165.       move     (r5)+n5                  ;and once more to odata                     <-----|
  166.       fmove                             x:(r6)+n6,d9.s y:(),d8.s      ;
  167.       fmove                                            y:(r1),d7.s    ;
  168.       fmpy d8,d7,d3                     x:(r1)+n1,d6.s                ;
  169.       fmpy d9,d6,d0                                                   ;
  170.       fmpy d9,d7,d1                                    y:(r1),d7.s    ;
  171.       fmpy d8,d6,d2  fadd d3,d0         x:(r0),d4.s                   ; Last groups are implemented as
  172.       fmove                             x:(r6)+n6,d9.s y:(),d8.s      ; single butterflies with storage to 
  173.       fmpy d8,d7,d3  faddsubr d4,d0     x:(r1)+n1,d6.s                ; the output data buffer. Data is stored 
  174.                                                                       ; in normal order, and the complex conjugate is
  175.                                                                       ; stored in the next output block using the 
  176.       fmpy d9,d6,d0  fsub d1,d2         d0.s,x:(r4)                   ; conjugate reverse counter r3
  177.       fmove                             d0.s,x:(r3)-n3 y:(r0)+n0,d5.s ;
  178.       fmpy d9,d7,d1  faddsubr d5,d2     d4.s,x:(r5)    y:(r1),d7.s    ;
  179.       fmove                             d4.s,x:(r3)+n3 y:(r6),d8.s    ;                                   
  180.       fadd d3,d0                        x:(r0),d4.s    d5.s,y:(r4)+n4 ;
  181.       fneg d5                                          d2.s,y:(r5)+n5 ;
  182.       fneg d2                           x:(r6)+n6,d9.s d5.s,y:(r3)-n3 ;
  183.       fmpy d8,d6,d2                                    d2.s,y:(r3)-n3 ;
  184.       fmpy d8,d7,d3  faddsubr d4,d0     x:(r1)+n1,d6.s                ;
  185. _end_last
  186.  
  187. ;
  188. ;Do second (four-point) complex fft (this has a "next to last" and "last pass"
  189. ;only with normal output storage and conjugate reverse storage of the next four
  190. ;points)
  191. ;
  192.            move (r2)+n2                      ;initialize input data pointer
  193. ;
  194. ; next to last pass
  195. ;
  196.       move #1,n2                        ;initialize number of groups
  197.       move r2,r0                        ;point to input data block
  198.       move r0,r4                        ;initialize pointers and offsets
  199.       lea (r0)+2,r1                     ;
  200.       move r1,r5                        ;
  201.       move #coef+coefsize/4,r6          ;
  202.       move #3,n0                        ;
  203.       move n0,n1                        ;
  204.       move n0,n4                        ;
  205.       move n0,n5                        ;
  206.       fmove                        x:(r6)+n6,d9.s  y:(),d8.s     ;
  207.       fmove                                        y:(r1),d7.s   ;
  208.       fmpy d8,d7,d3                x:(r1)+,d6.s                  ;
  209.       fmpy d9,d6,d0                                              ;
  210.       fmpy d9,d7,d1                                y:(r1),d7.s   ;
  211.       fmpy d8,d6,d2 fadd d3,d0     x:(r0),d4.s                   ;
  212.       fmpy d8,d7,d3 faddsubr d4,d0 x:(r1)+n1,d6.s                ;                             
  213.       fmpy d9,d6,d0 fsub d1,d2     d0.s,x:(r4)     y:(r0)+,d5.s  ;
  214.       fmpy d9,d7,d1 faddsubr d5,d2 d4.s,x:(r5)     y:(r1),d7.s   ;each group implemented as one 
  215.       fmpy d8,d6,d2 fadd d3,d0     x:(r0),d4.s     d2.s,y:(r5)+  ;four-point butterfly
  216.       fmove                        x:(r6)+n6,d9.s  y:(),d8.s     ;
  217.       fmpy d8,d7,d3 faddsubr d4,d0 x:(r1)+,d6.s    d5.s,y:(r4)+  ;
  218.       fmpy d9,d6,d0 fsub     d1,d2 d0.s,x:(r4)     y:(r0)+n0,d5.s
  219.       fmpy d9,d7,d1 faddsubr d5,d2 d4.s,x:(r5)     y:(r1),d7.s   ;
  220.       fmpy d8,d6,d2 fadd     d3,d0 x:(r0),d4.s     d2.s,y:(r5)+n5
  221.       fmpy d8,d7,d3 faddsubr d4,d0 x:(r1)+n1,d6.s  d5.s,y:(r4)+n4
  222. _end_next
  223. ;
  224. ; last pass
  225. ;
  226.       move n2,d0.l                 ;number of groups in last pass=
  227.       lsl d0   r2,r0               ;2*number of groups in previous pass. Point to input data block.
  228.       move d0.l,n2                 ;number of stages in this group -->n2
  229.       move n7,r4                   ;r4 points to A output
  230.       move #2*odata+points,r3      ;initialization of conjugate reverse pointer
  231.       move #-1,m3                  ;r3 (conjugate reverse pointer) decrements linearly in initialization
  232.       move r4,n3                   ;offset for conjugate pointer initialization
  233.       lea (r0)+,r1                 ;r1 points to B input
  234.       move (r3)-n3                 ;r3 now has end of next output data block
  235.       move #0,m3                   ;r3 will decrement bit-reversed in output storage
  236.       move #points/2,n3            ;correct offset for reverse counter
  237.       move #2,n0                   ;offset is 2 for A input pointer
  238.       lea (r3)+n3,r6               ;r6 now contains the next output pointer a starting address
  239.       move r6,n7                   ;n7 contains next output data block starting address
  240.       move #coef+coefsize/4,r6     ;r6 points to twiddle factors  
  241.       move n0,n1                   ;offset is 2 for B input pointer
  242.       move #points/4,n4            ;offset is #points/4 for A output pointer
  243.       move n4,n5                   ;offset is #points/4 for B output pointer
  244.       move #0,m4                   ;bit reversed addressing for A output pointer
  245.       lea (r4)+n4,r5               ;r5 points to B output by adding points/4 once----|
  246.       move m4,m5                   ;bit reversed addressing for B output pointer     |
  247.       move (r5)+n5                 ;and once more to odata                     <-----|
  248.       fmove                        x:(r6)+n6,d9.s  y:(),d8.s          ;
  249.       fmove                                       y:(r1),d7.s         ;
  250.       fmpy d8,d7,d3                x:(r1)+n1,d6.s                     ;
  251.       fmpy d9,d6,d0                                                   ;
  252.       fmpy d9,d7,d1                               y:(r1),d7.s         ;
  253.       fmpy d8,d6,d2 fadd d3,d0     x:(r0),d4.s                        ; Last groups are implemented as
  254.       fmove                        x:(r6)+n6,d9.s y:(),d8.s           ; single butterflies with storage to 
  255.       fmpy d8,d7,d3 faddsubr d4,d0 x:(r1)+n1,d6.s                     ; the output data buffer. Data is stored 
  256.                                                                       ; in normal order, and the complex conjugate is
  257.       do n2,_end_last                                                 ; stored in the next output block using the 
  258.       fmpy d9,d6,d0 fsub d1,d2     d0.s,x:(r4)                        ; conjugate reverse counter r3
  259.       fmove                        d0.s,x:(r3)-n3  y:(r0)+n0,d5.s     ;
  260.       fmpy d9,d7,d1 faddsubr d5,d2 d4.s,x:(r5)     y:(r1),d7.s        ;
  261.       fmove                        d4.s,x:(r3)+n3  y:(r6),d8.s        ;                                   
  262.       fadd d3,d0                   x:(r0),d4.s     d5.s,y:(r4)+n4     ;
  263.       fneg d5                                      d2.s,y:(r5)+n5     ;
  264.       fneg d2                      x:(r6)+n6,d9.s  d5.s,y:(r3)-n3     ;
  265.       fmpy d8,d6,d2                                d2.s,y:(r3)-n3     ;
  266.       fmpy d8,d7,d3 faddsubr d4,d0 x:(r1)+n1,d6.s                     ;
  267. _end_last
  268. ;
  269. ;Do all remaining complex fft's (starting with 8-point) with normally ordered
  270. ;output storage and conjugate reverse storage of the next output block
  271. ;
  272.       clr d9                                      ;initialize the # passes      
  273.       move #-1,m2                                 ;linear addressing for input data block pointer
  274.       move #8,n2                                  ;offset=8 for input data ptr.
  275.       move #4,d8                                  ;initialize number of FFT points
  276.       move (r2)+n2                                ;initialize r2  
  277.       do #@cvi(@log(points)/@log(2)-3.5),_endfft  ;do for all fft's. Ex.: 6 for 1024-pt.
  278.       
  279.       lsl d8                            ;new number of FFT pts = number of FFT points * 2
  280.       inc d9                            ;increment # passes
  281.       clr d2         d8.l,d1.l          ;number of FFT points -->d1
  282.       move d2.l,m6                      ;bit-reversed addr. for coef. ptr
  283.       move #1,d0.l                      ;initialize # groups          
  284.       move d8.l,n2                      ;offset for computing new input data block ptr.
  285.       move (r2)+n2                      ;point to next input data block
  286.  
  287.       do d9.l,_end_pass                 ;do for all passes
  288.       move d0.l,n2                      ;load number of groups
  289.       move r2,r0                        ;point to data
  290.       lsr  d1       #coef+coefsize/4,r6 ;# butterflies per group/2,r6 points to first coeff.
  291.       dec  d1      d1.l,n0              ;decrement number of butterflies twice
  292.       dec  d1      d1.l,n1              ;(first two butterflies are done separately)
  293.       move d1.l,n3                      ;number of butterflies per group-->n3
  294.       move n0,n4                        ;initialize pointers and pointer offsets
  295.       move n0,n5                        ;
  296.       lea (r0)+n0,r1                    ;
  297.       move r0,r4                        ;
  298.       move r1,r5                        ;
  299.       fmove                        x:(r6)+n6,d9.s y:(),d8.s      ;first two
  300.       fmove                                       y:(r1),d7.s    ;butterflies in this
  301.       fmpy d8,d7,d3                x:(r1)+,d6.s                  ;pass
  302.       fmpy d9,d6,d0                                              ;
  303.       fmpy d9,d7,d1                                 y:(r1),d7.s  ;
  304.       fmpy d8,d6,d2 fadd d3,d0     x:(r0),d4.s                   ;
  305.       fmpy d8,d7,d3 faddsubr d4,d0 x:(r1)+,d6.s                  ;
  306.  
  307.       do n2,_end_grp          ;do for all groups in this pass
  308.  
  309.       do n3,_end_bfy          ;do for all butterflies in this group
  310.       fmpy d9,d6,d0 fsub d1,d2     d0.s,x:(r4)    y:(r0)+,d5.s   ;4-instruction butterfly with
  311.       fmpy d9,d7,d1 faddsubr d5,d2 d4.s,x:(r5)    y:(r1),d7.s    ;constant twiddle
  312.       fmpy d8,d6,d2 fadd d3,d0     x:(r0),d4.s    d2.s,y:(r5)+   ;factor
  313.       fmpy d8,d7,d3 faddsubr d4,d0 x:(r1)+,d6.s   d5.s,y:(r4)+   ;
  314. _end_bfy
  315.       move (r1)+n1                                               ;first two
  316.       fmpy d9,d6,d0 fsub d1,d2     d0.s,x:(r4)    y:(r0)+,d5.s   ;butterflies in next
  317.       fmpy d9,d7,d1 faddsubr d5,d2 d4.s,x:(r5)    y:(r1),d7.s    ;pass
  318.       fmpy d8,d6,d2 fadd d3,d0     x:(r0),d4.s    d2.s,y:(r5)+   ;
  319.       fmove                        x:(r6)+n6,d9.s y:(),d8.s      ;
  320.       fmpy d8,d7,d3 faddsubr d4,d0 x:(r1)+,d6.s   d5.s,y:(r4)+   ;
  321.       fmpy d9,d6,d0 fsub     d1,d2 d0.s,x:(r4)    y:(r0)+n0,d5.s ;
  322.       fmpy d9,d7,d1 faddsubr d5,d2 d4.s,x:(r5)    y:(r1),d7.s    ;
  323.       fmpy d8,d6,d2 fadd     d3,d0 x:(r0),d4.s    d2.s,y:(r5)+n5 ;
  324.       fmpy d8,d7,d3 faddsubr d4,d0 x:(r1)+,d6.s   d5.s,y:(r4)+n4 ;
  325. _end_grp
  326.       move n2,d0.l                      ;number of groups for next pass=
  327.       lsl d0        n0,d1.l             ;2*number of groups for this pass
  328. _end_pass
  329. ;
  330. ; next to last pass
  331. ;
  332.       move      d0.l,n2            ;initialize number of groups
  333.       move      r2,r0              ;point to input data block
  334.       move      r0,r4              ;initialize pointers and offsets
  335.       lea      (r0)+2,r1           ;
  336.       move      r1,r5              ;
  337.       move      #coef+points/4,r6  ;
  338.       move      #3,n0              ;
  339.       move      n0,n1              ;
  340.       move      n0,n4              ;
  341.       move      n0,n5              ;
  342.       fmove                        x:(r6)+n6,d9.s y:(),d8.s      ;
  343.       fmove                                       y:(r1),d7.s    ;
  344.       fmpy d8,d7,d3                x:(r1)+,d6.s                  ;
  345.       fmpy d9,d6,d0                                              ;
  346.       fmpy d9,d7,d1                               y:(r1),d7.s    ;
  347.       fmpy d8,d6,d2 fadd d3,d0     x:(r0),d4.s                   ;
  348.       fmpy d8,d7,d3 faddsubr d4,d0 x:(r1)+n1,d6.s                ;
  349.                               
  350.       do n2,_end_next                                            ;do for all groups
  351.       fmpy d9,d6,d0 fsub d1,d2     d0.s,x:(r4)    y:(r0)+,d5.s   ;
  352.       fmpy d9,d7,d1 faddsubr d5,d2 d4.s,x:(r5)    y:(r1),d7.s    ;each group implemented as one 
  353.       fmpy d8,d6,d2 fadd d3,d0     x:(r0),d4.s    d2.s,y:(r5)+   ;four-point butterfly
  354.       fmove                        x:(r6)+n6,d9.s y:(),d8.s      ;
  355.       fmpy d8,d7,d3 faddsubr d4,d0 x:(r1)+,d6.s   d5.s,y:(r4)+   ;
  356.       fmpy d9,d6,d0 fsub d1,d2     d0.s,x:(r4)    y:(r0)+n0,d5.s
  357.       fmpy d9,d7,d1 faddsubr d5,d2 d4.s,x:(r5)    y:(r1),d7.s    ;
  358.       fmpy d8,d6,d2 fadd d3,d0     x:(r0),d4.s    d2.s,y:(r5)+n5
  359.       fmpy d8,d7,d3 faddsubr d4,d0 x:(r1)+n1,d6.s d5.s,y:(r4)+n4
  360. _end_next
  361. ;
  362. ; last pass
  363. ;
  364.       move n2,d0.l            ;number of groups in last pass=
  365.       lsl d0        r2,r0     ;2*number of groups in previous pass. Point to input data block.
  366.       move d0.l,n2            ;number of stages in this group -->n2
  367.       move n7,r4              ;r4 points to A output
  368.       move #2*odata+points,r3 ;initialization of conjugate reverse pointer
  369.       move #-1,m3             ;r3 (conjugate reverse pointer) decrements linearly in initialization
  370.       move r4,n3              ;offset for conjugate pointer initialization
  371.       lea (r0)+,r1            ;r1 points to B input
  372.       move (r3)-n3            ;r3 now has end of next output data block
  373.       move #0,m3              ;r3 will decrement bit-reversed in output storage
  374.       move #points/2,n3       ;correct offset for reverse counter
  375.       move #2,n0              ;offset is 2 for A input pointer
  376.       lea (r3)+n3,r6          ;r6 now contains the next output pointer a starting address
  377.       move r6,n7              ;n7 contains next output data block starting address
  378.       move #coef+points/4,r6  ;r6 points to twiddle factors  
  379.       move n0,n1              ;offset is 2 for B input pointer
  380.       move #points/4,n4       ;offset is #points/4 for A output pointer
  381.       move n4,n5              ;offset is #points/4 for B output pointer
  382.       move #0,m4              ;bit reversed addressing for A output pointer
  383.       lea (r4)+n4,r5          ;r5 points to B output by adding points/4 once----|
  384.       move m4,m5              ;bit reversed addressing for B output pointer     |
  385.       move (r5)+n5            ;and once more to odata                     <-----|
  386.       fmove                        x:(r6)+n6,d9.s y:(),d8.s           ;
  387.       fmove                                       y:(r1),d7.s         ;
  388.       fmpy d8,d7,d3                x:(r1)+n1,d6.s                     ;
  389.       fmpy d9,d6,d0                                                   ;
  390.       fmpy d9,d7,d1                                y:(r1),d7.s        ;
  391.       fmpy d8,d6,d2 fadd d3,d0     x:(r0),d4.s                        ; Last groups are implemented as
  392.       fmove                        x:(r6)+n6,d9.s  y:(),d8.s          ; single butterflies with storage to 
  393.       fmpy d8,d7,d3 faddsubr d4,d0 x:(r1)+n1,d6.s                     ; the output data buffer. Data is stored 
  394.                                                                       ; in normal order, and the complex conjugate is
  395.       do n2,_end_last                                                 ; stored in the next output block using the 
  396.       fmpy d9,d6,d0 fsub d1,d2     d0.s,x:(r4)                        ; conjugate reverse counter r3
  397.       fmove                        d0.s,x:(r3)-n3  y:(r0)+n0,d5.s     ;
  398.       fmpy d9,d7,d1 faddsubr d5,d2 d4.s,x:(r5)     y:(r1),d7.s        ;
  399.       fmove                        d4.s,x:(r3)+n3  y:(r6),d8.s        ;                                   
  400.       fadd d3,d0                   x:(r0),d4.s     d5.s,y:(r4)+n4     ;
  401.       fneg d5                                      d2.s,y:(r5)+n5     ;
  402.       fneg d2                      x:(r6)+n6,d9.s  d5.s,y:(r3)-n3     ;
  403.       fmpy d8,d6,d2                                d2.s,y:(r3)-n3     ;
  404.       fmpy d8,d7,d3 faddsubr d4,d0 x:(r1)+n1,d6.s                     ;
  405. _end_last
  406. _endfft
  407.      jmp  strt           ;go back and start new fft
  408.